package com.duoduo.common.fliter;

import com.alibaba.fastjson.JSONObject;
import com.duoduo.common.response.Result;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;

import javax.servlet.*;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;

/**
 * 全局Token过滤器</br>
 * 对登录请求放行</br>
 */
@Component
public class JWTTokenFilter implements Filter {

    @Autowired
    private StatelessRealm statelessRealm;

    // 主认证方法
    private boolean isAccessAllowed(ServletRequest servletRequest, ServletResponse servletResponse){
        HttpServletRequest request = (HttpServletRequest) servletRequest;
        if(isLoginRequest(servletRequest,servletResponse)){// 将登录请求放行
            return true;
        }
        String tokenStr = request.getHeader("token");
        if(tokenStr == null){// 请求头中没有Token
            return false;
        }

        return statelessRealm.doAuthentication(tokenStr);// 认证Token
    }

    // 设置放行接口
    private boolean isLoginRequest(ServletRequest request, ServletResponse response) {
        HttpServletRequest httpServletRequest = (HttpServletRequest) request;
        // 如果是以POST请求访问token资源，则该请求为登录请求
        if(httpServletRequest.getRequestURI().contains("login")&&"POST".equals(httpServletRequest.getMethod())){ // 跳过登录请求
            return true;
        }else if(httpServletRequest.getRequestURI().contains("test")){// 测试接口
            return true;
        }else if(httpServletRequest.getRequestURI().contains("swagger-")){ // 释放Swagger页面
            return true;
        }else if(httpServletRequest.getRequestURI().contains("v3")){// 释放Swagger页面内容
            return true;
        }else if(httpServletRequest.getRequestURI().contains("register")&& "POST".equals(httpServletRequest.getMethod())){// 释放注册通道
            return true;
        }
        return false;
    }

    /**
     * 返回认证失败的响应
     * @param servletResponse
     * @throws IOException
     */
    private void onAuthenticationFail(ServletResponse servletResponse,String errorMsg) throws IOException {
        HttpServletResponse httpResponse = (HttpServletResponse) servletResponse;
        // httpResponse.setStatus(HttpServletResponse.SC_UNAUTHORIZED);
        Result result = Result.builder().code(401).msg(errorMsg).build();
        httpResponse.setCharacterEncoding("utf-8");
        httpResponse.setContentType("application/json");
        httpResponse.getWriter().write(JSONObject.toJSONString(result));
    }

    @Override
    public void init(FilterConfig filterConfig) throws ServletException {

    }

    @Override
    public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws ServletException, IOException {
        if(isAccessAllowed(servletRequest,servletResponse)){// Token认证通过或访问登录接口
            filterChain.doFilter(servletRequest,servletResponse);
        }else{// Token认证失败
            //throw new JWTDecodeException("认证失败！或登录已过期!");
            onAuthenticationFail(servletResponse,"认证失败！或登录已过时");
        }
    }

    @Override
    public void destroy() {

    }
}
